// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者，助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件，未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------

// #ifdef APP-PLUS
import permision from "./permission.js"
// #endif

/**
 * 全局定位权限管理和数据缓存
 */
class LocationManager {
  constructor() {
    this.locationData = null;
    this.hasLocationPermission = false;
    this.permissionStatus = 0; // 0: 未检查, 1: 已允许, 2: 拒绝, 3: 系统未开启
    this.isChecking = false;
    this.listeners = [];
  }

  /**
   * 初始化定位管理器
   */
  init() {
    // 从缓存中恢复定位数据
    this.restoreLocationData();
    // 检查权限状态
    this.checkInitialPermission();
  }

  /**
   * 从缓存中恢复定位数据
   */
  restoreLocationData() {
    try {
      // 优先使用新的对象缓存格式
      const cachedLocationInfo = uni.getStorageSync('location_info');
      if (cachedLocationInfo && typeof cachedLocationInfo === 'object') {
        this.locationData = {
          latitude: parseFloat(cachedLocationInfo.latitude),
          longitude: parseFloat(cachedLocationInfo.longitude),
          name: cachedLocationInfo.name || '',
          address: cachedLocationInfo.address || '',
          updateTime: cachedLocationInfo.updateTime || 0,
          source: cachedLocationInfo.source || '', // 恢复数据来源标识
          type: cachedLocationInfo.type || '' // 恢复位置类型
        };
        this.hasLocationPermission = cachedLocationInfo.hasPermission || false;
        this.permissionStatus = cachedLocationInfo.hasPermission ? 1 : 0;
        return;
      }
      
      // 兼容旧版本的独立缓存项
      const latitude = uni.getStorageSync('user_latitude');
      const longitude = uni.getStorageSync('user_longitude');
      const locationName = uni.getStorageSync('user_location_name');
      const locationAddress = uni.getStorageSync('user_location_address');
      const updateTime = uni.getStorageSync('location_update_time');
      const hasPermission = uni.getStorageSync('has_location_permission');
      
      if (latitude && longitude) {
        this.locationData = {
          latitude: parseFloat(latitude),
          longitude: parseFloat(longitude),
          name: locationName || '',
          address: locationAddress || '',
          updateTime: updateTime || 0
        };
        this.hasLocationPermission = !!hasPermission;
        this.permissionStatus = hasPermission ? 1 : 0;
        
        // 迁移到新格式并清除旧缓存
        this.migrateToNewFormat();
      }
    } catch (error) {
    }
  }

  /**
   * 迁移旧格式缓存到新格式
   */
  migrateToNewFormat() {
    try {
      
      // 保存到新格式
      this.saveLocationDataToCache();
      
      // 清除旧格式缓存
      uni.removeStorageSync('user_latitude');
      uni.removeStorageSync('user_longitude');
      uni.removeStorageSync('user_location_name');
      uni.removeStorageSync('user_location_address');
      uni.removeStorageSync('location_update_time');
      uni.removeStorageSync('has_location_permission');
      
    } catch (error) {
    }
  }

  /**
   * 保存位置数据到缓存（使用对象格式）
   */
  saveLocationDataToCache() {
    try {
      const locationInfo = {
        latitude: this.locationData?.latitude || 0,
        longitude: this.locationData?.longitude || 0,
        name: this.locationData?.name || '',
        address: this.locationData?.address || '',
        updateTime: this.locationData?.updateTime || Date.now(),
        hasPermission: this.hasLocationPermission,
        permissionStatus: this.permissionStatus,
        source: this.locationData?.source || '', // 保存数据来源标识
        type: this.locationData?.type || '', // 保存位置类型
        version: '2.0' // 版本标识
      };
      
      uni.setStorageSync('location_info', locationInfo);
    } catch (error) {
    }
  }

  /**
   * 检查初始权限状态
   */
  async checkInitialPermission() {
    if (this.isChecking) return this.permissionStatus;
    
    this.isChecking = true;
    
    try {
      let status = 0;
      
      // #ifdef APP-PLUS
      status = permision.isIOS ? 
        await permision.requestIOS('location') : 
        await permision.requestAndroid('android.permission.ACCESS_FINE_LOCATION');
      // #endif
      
      // #ifdef MP
      status = await this.getSetting();
      // #endif
      
      // #ifdef H5
      // H5环境下通过尝试获取定位来判断权限
      try {
        await this.testLocationAccess();
        status = 1;
      } catch (error) {
        status = 2;
      }
      // #endif
      
      this.permissionStatus = status;
      this.hasLocationPermission = status === 1;
      
    } catch (error) {
      this.permissionStatus = 2;
      this.hasLocationPermission = false;
    } finally {
      this.isChecking = false;
    }
    
    return this.permissionStatus;
  }

  /**
   * 测试定位访问权限（H5环境）
   */
  testLocationAccess() {
    return new Promise((resolve, reject) => {
      // #ifdef H5
      if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(
          (position) => resolve(position),
          (error) => {
            reject(error);
          },
          { timeout: 10000, enableHighAccuracy: false, maximumAge: 60000 }
        );
      } else {
        reject(new Error('Geolocation not supported'));
      }
      // #endif
      
      // #ifndef H5
      // 非H5环境直接resolve，由其他逻辑处理
      resolve(true);
      // #endif
    });
  }

  /**
   * 获取小程序定位权限设置
   */
  getSetting() {
    return new Promise((resolve) => {
      // #ifdef MP
      uni.getSetting({
        success: (res) => {
          if (res.authSetting['scope.userLocation'] === undefined) {
            resolve(0); // 未询问
          } else if (res.authSetting['scope.userLocation']) {
            resolve(1); // 已允许
          } else {
            resolve(2); // 已拒绝
          }
        },
        fail: () => resolve(2)
      });
      // #endif
      
      // #ifndef MP
      resolve(0);
      // #endif
    });
  }

  /**
   * 实时检查系统权限状态（不依赖缓存）
   */
  async checkRealTimePermission() {
    
    try {
      let status = 0;
      
      // #ifdef APP-PLUS
      status = permision.isIOS ? 
        await permision.requestIOS('location') : 
        await permision.requestAndroid('android.permission.ACCESS_FINE_LOCATION');
      // #endif
      
      // #ifdef MP
      status = await this.getSetting();
      // #endif
      
      // #ifdef H5
      // H5环境下通过实际尝试获取定位来检查权限
      try {
        await this.testLocationAccess();
        status = 1;
      } catch (error) {
        status = 2;
      }
      // #endif
      
      return status;
      
    } catch (error) {
      return 2; // 检查失败视为无权限
    }
  }

  /**
   * 请求定位权限并获取位置信息
   */
  async requestLocationPermission(showTip = true) {
    if (this.isChecking) return false;
    
    try {
      const permissionStatus = await this.checkInitialPermission();
      
      if (permissionStatus === 1) {
        // 权限已获得，尝试获取定位
        try {
          const locationData = await this.getCurrentLocation();
          if (locationData) {
            await this.saveLocationData(locationData);
            this.notifyListeners('permission_granted', locationData);
            return true;
          }
        } catch (locationError) {
          if (showTip) {
            this.showLocationErrorDialog(locationError.userMessage);
          }
          return false;
        }
      } else if (permissionStatus === 2) {
        // 权限被拒绝
        if (showTip) {
          this.showLocationPermissionDeniedDialog();
        }
        this.notifyListeners('permission_denied');
        return false;
      } else if (permissionStatus === 0) {
        // 未询问权限，尝试获取定位
        try {
          const locationData = await this.getCurrentLocation();
          if (locationData) {
            await this.saveLocationData(locationData);
            this.permissionStatus = 1;
            this.hasLocationPermission = true;
            this.notifyListeners('permission_granted', locationData);
            return true;
          }
        } catch (locationError) {
          // 首次获取失败可能是用户拒绝，更新状态
          this.permissionStatus = 2;
          this.hasLocationPermission = false;
          if (showTip) {
            this.showLocationPermissionDeniedDialog();
          }
          return false;
        }
      }
    } catch (error) {
      if (showTip) {
        this.showLocationErrorDialog();
      }
      this.notifyListeners('permission_error', error);
    }
    
    return false;
  }

  /**
   * 获取当前位置信息
   */
  getCurrentLocation() {
    return new Promise((resolve, reject) => {
      // 小程序定位参数优化
      const locationOptions = {
        // #ifdef MP
        type: 'wgs84',        // 小程序推荐使用wgs84，兼容性更好
        isHighAccuracy: false, // 降低精度要求，提高成功率
        timeout: 15000,       // 设置超时时间15秒
        // #endif
        
        // #ifdef H5 || APP-PLUS
        type: 'gcj02',
        isHighAccuracy: true,
        timeout: 10000,
        // #endif
      };
      
      // 开始获取位置
      
      uni.getLocation({
        ...locationOptions,
        success: (res) => {
          const locationData = {
            latitude: res.latitude,
            longitude: res.longitude,
            accuracy: res.accuracy,
            altitude: res.altitude,
            speed: res.speed,
            updateTime: Date.now()
          };
          resolve(locationData);
        },
        fail: (error) => {
          // 获取定位失败
          
          // 根据具体错误提供更详细的信息
          let errorMessage = '获取位置失败';
          if (error.errMsg) {
            if (error.errMsg.includes('timeout')) {
              errorMessage = '定位超时，请检查网络连接和GPS设置';
            } else if (error.errMsg.includes('system permission denied')) {
              errorMessage = '系统定位权限被拒绝，请在系统设置中开启定位服务';
            } else if (error.errMsg.includes('location service unavailable')) {
              errorMessage = '定位服务不可用，请确保GPS已开启';
            } else if (error.errMsg.includes('network')) {
              errorMessage = '网络定位失败，请检查网络连接';
            }
          }
          
          error.userMessage = errorMessage;
          reject(error);
        }
      });
    });
  }

  /**
   * 保存定位数据到缓存
   * @param {Object} locationData 位置数据
   * @param {String} locationName 位置名称
   * @param {String} locationAddress 位置地址
   * @param {Boolean} skipPermissionCheck 是否跳过权限检查（用于地图选择场景）
   */
  async saveLocationData(locationData, locationName = '', locationAddress = '', skipPermissionCheck = false) {
    
    let canSave = false;
    
    if (skipPermissionCheck) {
      // 地图选择场景，跳过权限检查
      canSave = true;
    } else {
      // GPS定位场景，需要检查权限
      const realTimePermissionStatus = await this.checkRealTimePermission();
      canSave = realTimePermissionStatus === 1;
    }
    
    if (canSave) {
      this.locationData = {
        ...locationData,
        name: locationName,
        address: locationAddress,
        source: skipPermissionCheck ? 'manual_select' : 'gps', // 根据场景设置数据来源
        type: skipPermissionCheck ? 'business' : 'gps' // 根据场景设置位置类型
      };
      
      // 设置位置选择成功标识
      this.hasLocationPermission = true;
      this.permissionStatus = 1;
      
      // 使用新的对象格式保存到缓存
      this.saveLocationDataToCache();
      
    } else {
      // 清除可能过期的权限标识和位置数据
      this.hasLocationPermission = false;
      this.permissionStatus = 2;
      this.clearLocationData();
    }
  }

  /**
   * 清除定位数据
   */
  clearLocationData() {
    
    this.locationData = null;
    this.hasLocationPermission = false;
    this.permissionStatus = 2;
    
    // 清除新格式缓存
    uni.removeStorageSync('location_info');
    
    // 兼容性：清除可能存在的旧格式缓存
    uni.removeStorageSync('user_latitude');
    uni.removeStorageSync('user_longitude');
    uni.removeStorageSync('user_location_name');
    uni.removeStorageSync('user_location_address');
    uni.removeStorageSync('location_update_time');
    uni.removeStorageSync('has_location_permission');
    
  }

  /**
   * 清理历史圈层缓存（小程序首次启动时使用）
   */
  clearHistoricalAreaCache() {
    try {
      // 清除areas_info缓存
      uni.removeStorageSync('areas_info');
    } catch (error) {
      console.warn('清理历史圈层缓存失败:', error);
    }
  }

  /**
   * 检查是否有定位权限（实时检查）
   */
  async hasPermission() {
    
    // 检查是否已有用户选择的地址，如果有就不要覆盖
    const cachedLocationInfo = uni.getStorageSync('location_info');
    if (cachedLocationInfo && (cachedLocationInfo.source === 'manual_select' || cachedLocationInfo.type === 'business')) {
      // 直接返回权限状态，不触发GPS定位
      this.permissionStatus = 1;
      this.hasLocationPermission = true;
      return true;
    }
    
    // 进行实时权限检查而不是依赖缓存
    const realTimeStatus = await this.checkRealTimePermission();
    
    // 更新内部状态
    this.permissionStatus = realTimeStatus;
    this.hasLocationPermission = realTimeStatus === 1;
    
    // 如果权限被撤销，清除相关缓存
    if (realTimeStatus !== 1) {
      this.clearLocationData();
    } else {
      // 权限有效，更新缓存标识（但不覆盖位置数据）
      if (!cachedLocationInfo) {
        this.saveLocationDataToCache();
      }
    }
    
    return this.hasLocationPermission;
  }

  /**
   * 获取缓存的定位数据（实时从缓存读取）
   */
  getLocationData() {
    // 实时从缓存读取最新数据，而不是返回内存中的旧数据
    const cachedLocationInfo = uni.getStorageSync('location_info');
    if (cachedLocationInfo && typeof cachedLocationInfo === 'object') {
      return {
        latitude: parseFloat(cachedLocationInfo.latitude),
        longitude: parseFloat(cachedLocationInfo.longitude),
        name: cachedLocationInfo.name || '',
        address: cachedLocationInfo.address || '',
        updateTime: cachedLocationInfo.updateTime || 0,
        source: cachedLocationInfo.source || '',
        type: cachedLocationInfo.type || ''
      };
    }
    
    // 如果没有缓存，返回内存中的数据（兼容旧逻辑）
    return this.locationData;
  }

  /**
   * 获取完整的位置信息（包括缓存状态）
   */
  getFullLocationInfo() {
    const cachedLocationInfo = uni.getStorageSync('location_info');
    return {
      locationData: this.locationData,
      hasPermission: this.hasLocationPermission,
      permissionStatus: this.permissionStatus,
      isExpired: this.isLocationDataExpired(),
      cachedInfo: cachedLocationInfo,
      cacheExists: !!cachedLocationInfo
    };
  }

  /**
   * 检查缓存是否存在且有效
   */
  isCacheValid() {
    const cachedLocationInfo = uni.getStorageSync('location_info');
    if (!cachedLocationInfo || typeof cachedLocationInfo !== 'object') {
      return false;
    }
    
    // 检查必要字段
    if (!cachedLocationInfo.latitude || !cachedLocationInfo.longitude) {
      return false;
    }
    
    // 检查是否过期
    if (this.isLocationDataExpired()) {
      return false;
    }
    
    return true;
  }


  /**
   * 判断定位数据是否过期（默认30分钟）
   */
  isLocationDataExpired(maxAge = 30 * 60 * 1000) {
    if (!this.locationData || !this.locationData.updateTime) {
      return true;
    }
    
    return (Date.now() - this.locationData.updateTime) > maxAge;
  }

  /**
   * 显示定位权限被拒绝的对话框
   */
  showLocationPermissionDeniedDialog() {
    // #ifdef MP
    // 小程序：提供详细的权限开启步骤
    uni.showModal({
      title: '需要位置权限',
      content: '为了为您推荐附近商圈，需要获取位置权限。\n\n您可以：\n• 点击"去设置"在小程序设置中开启\n• 或重新进入页面时选择"允许"',
      showCancel: true,
      cancelText: '稍后再说', 
      confirmText: '去设置',
      confirmColor: '#f55850',
      success: (res) => {
        if (res.confirm) {
          this.openLocationSetting();
        }
      }
    });
    // #endif
    
    // #ifdef H5
    // H5：浏览器权限引导
    uni.showModal({
      title: '需要位置权限',
      content: '为了为您推荐附近商圈，需要获取位置权限。\n\n请在浏览器中：\n• 点击地址栏左侧的位置图标\n• 选择"始终允许"\n• 刷新页面重试',
      showCancel: true,
      cancelText: '知道了',
      confirmText: '我已设置',
      confirmColor: '#f55850',
      success: (res) => {
        if (res.confirm) {
          // H5 中重新尝试获取权限
          location.reload();
        }
      }
    });
    // #endif
    
    // #ifdef APP-PLUS
    // APP：系统权限引导
    uni.showModal({
      title: '需要位置权限',
      content: '为了为您推荐附近商圈，需要获取位置权限。\n\n请在系统设置中：\n• 找到本应用\n• 开启"位置信息"权限\n• 返回应用重试',
      showCancel: true,
      cancelText: '稍后再说',
      confirmText: '去设置',
      confirmColor: '#f55850',
      success: (res) => {
        if (res.confirm) {
          this.openLocationSetting();
        }
      }
    });
    // #endif
  }

  /**
   * 显示定位错误对话框
   */
  showLocationErrorDialog(customMessage) {
    if (customMessage) {
      // 使用自定义错误消息
      uni.showModal({
        title: '定位失败',
        content: customMessage,
        showCancel: true,
        cancelText: '稍后再试',
        confirmText: '重新定位',
        confirmColor: '#f55850',
        success: (res) => {
          if (res.confirm) {
            this.requestLocationPermission(false);
          }
        }
      });
      return;
    }
    
    // #ifdef MP
    // 小程序：针对性的问题排查
    uni.showModal({
      title: '定位失败',
      content: '获取位置信息失败，请检查：\n\n• 手机GPS定位是否开启\n• 网络连接是否正常\n• 微信位置权限是否已授权\n\n建议重新进入页面再试',
      showCancel: true,
      cancelText: '稍后再试',
      confirmText: '重新定位',
      confirmColor: '#f55850',
      success: (res) => {
        if (res.confirm) {
          this.requestLocationPermission(false);
        }
      }
    });
    // #endif
    
    // #ifdef H5
    // H5：浏览器特有问题
    uni.showModal({
      title: '定位失败',
      content: '获取位置信息失败，请检查：\n\n• 浏览器位置权限是否已开启\n• 网络连接是否正常\n• 是否允许HTTPS访问位置\n\n建议刷新页面重试',
      showCancel: true,
      cancelText: '稍后再试',
      confirmText: '刷新重试',
      confirmColor: '#f55850',
      success: (res) => {
        if (res.confirm) {
          location.reload();
        }
      }
    });
    // #endif
    
    // #ifdef APP-PLUS
    // APP：系统级问题
    uni.showModal({
      title: '定位失败',
      content: '获取位置信息失败，请检查：\n\n• 系统位置服务是否开启\n• 应用位置权限是否已授权\n• 网络连接是否正常\n\n建议检查系统设置后重试',
      showCancel: true,
      cancelText: '稍后再试',
      confirmText: '重新定位',
      confirmColor: '#f55850',
      success: (res) => {
        if (res.confirm) {
          this.requestLocationPermission(false);
        }
      }
    });
    // #endif
  }

  /**
   * 打开定位设置
   */
  openLocationSetting() {
    // #ifdef APP-PLUS
    if (permision) {
      permision.gotoAppSetting();
    }
    // #endif
    
    // #ifdef MP
    uni.openSetting({
      success: (res) => {
        if (res.authSetting && res.authSetting['scope.userLocation']) {
          this.requestLocationPermission(false);
        }
      }
    });
    // #endif
    
    // #ifdef H5
    uni.showToast({
      title: '请在浏览器设置中允许位置访问',
      icon: 'none',
      duration: 3000
    });
    // #endif
  }

  /**
   * 决定跳转路径
   */
  getLocationPagePath() {
    if (this.hasLocationPermission && this.locationData) {
      return '/pages/circle/select';
    } else {
      return '/pages/circle/index';
    }
  }

  /**
   * 智能跳转到定位页面
   */
  navigateToLocationPage(params = {}) {
    const path = this.getLocationPagePath();
    const url = Object.keys(params).length > 0 ? 
      `${path}?${Object.keys(params).map(key => `${key}=${encodeURIComponent(params[key])}`).join('&')}` : 
      path;
    
    uni.navigateTo({
      url: url,
      fail: () => {
        // 如果跳转失败，尝试重定向
        uni.redirectTo({ url: url });
      }
    });
  }

  /**
   * 添加监听器
   */
  addListener(callback) {
    this.listeners.push(callback);
  }

  /**
   * 移除监听器
   */
  removeListener(callback) {
    const index = this.listeners.indexOf(callback);
    if (index > -1) {
      this.listeners.splice(index, 1);
    }
  }

  /**
   * 通知所有监听器
   */
  notifyListeners(event, data) {
    this.listeners.forEach(callback => {
      try {
        callback(event, data);
      } catch (error) {
      }
    });
  }

  /**
   * 刷新定位数据 - 改为使用地图选择
   */
  async refreshLocationData(showLoading = true) {
    
    return new Promise((resolve, reject) => {
      // 使用当前位置作为地图中心点（如果有的话）
      const chooseLocationOptions = {};
      if (this.locationData) {
        chooseLocationOptions.latitude = this.locationData.latitude;
        chooseLocationOptions.longitude = this.locationData.longitude;
      }
      
      // 直接打开系统地图选择位置
      uni.chooseLocation({
        ...chooseLocationOptions,
        success: async (res) => {
          
          try {
            // 保存用户选择的位置（跳过权限检查）
            await this.saveLocationData({
              latitude: res.latitude,
              longitude: res.longitude,
              updateTime: Date.now()
            }, res.name, res.address, true);
            
            if (showLoading) {
              uni.showToast({
                title: '位置已更新',
                icon: 'success'
              });
            }
            
            resolve(this.locationData);
          } catch (error) {
            if (showLoading) {
              uni.showToast({
                title: '保存位置失败',
                icon: 'none'
              });
            }
            reject(error);
          }
        },
        fail: (error) => {
          
          // 如果不是用户取消，显示错误提示
          if (showLoading && error.errMsg && !error.errMsg.includes('cancel')) {
            uni.showToast({
              title: '位置选择失败',
              icon: 'none'
            });
          }
          
          // 用户取消也算是一种处理结果，返回null而不是reject
          resolve(null);
        }
      });
    });
  }
}

// 创建全局单例
const locationManager = new LocationManager();

export default locationManager;